package org.bird.classloader;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * 自定义类加载器:实现java类混淆加密
 * 
 * @author liangjf
 *
 */
public class MyClassLoader extends java.lang.ClassLoader {

	// 需要加载类.class文件的目录
	private String classFile;

	// 无参的构造方法，用于class.newInstance()构造对象使用
	public MyClassLoader() {
		classFile = MyClassLoader.class.getResource("").getPath() + "ClassLoaderAttachment1.class";
	}

	public MyClassLoader(String classDir) {
		this.classFile = classDir;
	}

	protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
		if (name.equals("org.bird.classloader.ClassLoaderAttachment")) {
			return findClass(name);
		} else {
			return super.loadClass(name, resolve);
		}
	}

	protected Class<?> findClass(String name) throws ClassNotFoundException {
		try {
			// 将class文件进行解密
			FileInputStream fis = new FileInputStream(classFile);
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			encodeAndDecode(fis, bos);
			byte[] classByte = bos.toByteArray();
			// 将字节流变成一个class
			return defineClass(name, classByte, 0, classByte.length);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return super.findClass(name);
	}

	/**
	 * 加密和解密算法
	 * 
	 * @param is
	 * @param os
	 * @throws Exception
	 */
	private static void encodeAndDecode(InputStream is, OutputStream os) throws Exception {
		int bytes = -1;
		while ((bytes = is.read()) != -1) {
			bytes = bytes ^ 0xff;// 和0xff进行异或处理
			os.write(bytes);
		}
	}

	// 测试，先将ClassLoaderAttachment.class文件加密写到工程的class_temp目录下
	public static void main(String[] args) throws Exception {
		String path = MyClassLoader.class.getResource("").getPath();
		String srcPath = path + "ClassLoaderAttachment.class";
		String desPath = path;// ClassLoaderAttachment.class输出的路径
		String desPathFile = desPath + File.separator + "ClassLoaderAttachment1.class";
		File file = new File(desPathFile);
		if (!file.exists()) {
			file.getParentFile().mkdirs();
			file.createNewFile();
		}

		FileInputStream fis = new FileInputStream(srcPath);
		FileOutputStream fos = new FileOutputStream(desPathFile);
		// 将class进行加密
		encodeAndDecode(fis, fos);
		fos.flush();
		fis.close();
		fos.close();

		MyClassLoader classLoader = new MyClassLoader();
		Class<?> clazz = classLoader.loadClass("org.bird.classloader.ClassLoaderAttachment");
		Object obj = clazz.newInstance();
		System.out.println(obj);
		System.out.println(obj.getClass().getClassLoader());// 打印出我们的自定义类加载器
		System.out.println(obj.getClass().getClassLoader().getParent());// 打印出AppClassLoader类加载器
		System.out.println(obj.getClass().getClassLoader().getParent().getParent());// 打印出ExtClassLoader类加载器
	}

}
